From 2b19e2fc1f6dc7436e5650e2394ba33230ab48ca Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Wed, 22 Jul 2020 02:50:58 +0200 Subject: [PATCH] sortlistmodel: Add progress estimation --- docs/reference/gtk/gtk4-sections.txt | 1 + gtk/gtksortlistmodel.c | 69 ++++++++++++++++++++++++++++ gtk/gtksortlistmodel.h | 3 ++ 3 files changed, 73 insertions(+) diff --git a/docs/reference/gtk/gtk4-sections.txt b/docs/reference/gtk/gtk4-sections.txt index 8b87e917ad..5f2355d83c 100644 --- a/docs/reference/gtk/gtk4-sections.txt +++ b/docs/reference/gtk/gtk4-sections.txt @@ -2834,6 +2834,7 @@ gtk_sort_list_model_set_model gtk_sort_list_model_get_model gtk_sort_list_model_set_incremental gtk_sort_list_model_get_incremental +gtk_sort_list_model_get_peanding GTK_SORT_LIST_MODEL GTK_IS_SORT_LIST_MODEL diff --git a/gtk/gtksortlistmodel.c b/gtk/gtksortlistmodel.c index d3f04a5c64..f79bb77a1e 100644 --- a/gtk/gtksortlistmodel.c +++ b/gtk/gtksortlistmodel.c @@ -72,6 +72,7 @@ enum { PROP_0, PROP_INCREMENTAL, PROP_MODEL, + PROP_PENDING, PROP_SORTER, NUM_PROPERTIES }; @@ -188,6 +189,8 @@ gtk_sort_list_model_stop_sorting (GtkSortListModel *self, gtk_tim_sort_get_runs (&self->sort, runs); gtk_tim_sort_finish (&self->sort); g_clear_handle_id (&self->sort_cb, g_source_remove); + + g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_PENDING]); } static gboolean @@ -268,6 +271,7 @@ gtk_sort_list_model_sort_cb (gpointer data) { if (n_items) g_list_model_items_changed (G_LIST_MODEL (self), pos, n_items, n_items); + g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_PENDING]); return G_SOURCE_CONTINUE; } @@ -312,6 +316,7 @@ gtk_sort_list_model_start_sorting (GtkSortListModel *self, return FALSE; self->sort_cb = g_idle_add (gtk_sort_list_model_sort_cb, self); + g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_PENDING]); return TRUE; } @@ -652,6 +657,10 @@ gtk_sort_list_model_get_property (GObject *object, g_value_set_object (value, self->model); break; + case PROP_PENDING: + g_value_set_uint (value, gtk_sort_list_model_get_pending (self)); + break; + case PROP_SORTER: g_value_set_object (value, self->sorter); break; @@ -782,6 +791,18 @@ gtk_sort_list_model_class_init (GtkSortListModelClass *class) G_TYPE_LIST_MODEL, GTK_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY); + /** + * GtkSortListModel:pending: + * + * Estimate of unsorted items remaining + */ + properties[PROP_PENDING] = + g_param_spec_uint ("pending", + P_("Pending"), + P_("Estimate of unsorted items remaining"), + 0, G_MAXUINT, 0, + GTK_PARAM_READABLE | G_PARAM_EXPLICIT_NOTIFY); + /** * GtkSortListModel:sorter: * @@ -990,3 +1011,51 @@ gtk_sort_list_model_get_incremental (GtkSortListModel *self) return self->incremental; } + +/** + * gtk_sort_list_model_get_pending: + * @self: a #GtkSortListModel + * + * Estimates progress of an ongoing sorting operation + * + * The estimate is the number of items that would still need to be + * sorted to finish the sorting operation if this was a linear + * algorithm. So this number is not related to how many items are + * already correctly sorted. + * + * If you want to estimate the progress, you can use code like this: + * |[ + * double progress = 1.0 - (double) gtk_sort_list_model_get_pending (self) + * / MAX (1, g_list_model_get_n_items (G_LIST_MODEL (sort))); + * ]| + * + * If no sort operation is ongoing - in particular when + * #GtkSortListModel:incremental is %FALSE - this function returns 0. + * + * Returns: a progress estimate of remaining items to sort + **/ +guint +gtk_sort_list_model_get_pending (GtkSortListModel *self) +{ + g_return_val_if_fail (GTK_IS_SORT_LIST_MODEL (self), FALSE); + + if (self->sort_cb == 0) + return 0; + + /* We do a random guess that 50% of time is spent generating keys + * and the other 50% is spent actually sorting. + * + * This is of course massively wrong, but it depends on the sorter + * in use, and estimating this correctly is hard, so this will have + * to be good enough. + */ + if (!gtk_bitset_is_empty (self->missing_keys)) + { + return (self->n_items + gtk_bitset_get_size (self->missing_keys)) / 2; + } + else + { + return (self->n_items - gtk_tim_sort_get_progress (&self->sort)) / 2; + } +} + diff --git a/gtk/gtksortlistmodel.h b/gtk/gtksortlistmodel.h index c4efdd80f3..5dc37cbf70 100644 --- a/gtk/gtksortlistmodel.h +++ b/gtk/gtksortlistmodel.h @@ -58,6 +58,9 @@ void gtk_sort_list_model_set_incremental (GtkSortListMode GDK_AVAILABLE_IN_ALL gboolean gtk_sort_list_model_get_incremental (GtkSortListModel *self); +GDK_AVAILABLE_IN_ALL +guint gtk_sort_list_model_get_pending (GtkSortListModel *self); + G_END_DECLS #endif /* __GTK_SORT_LIST_MODEL_H__ */ -- 2.30.2